package view
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	
	import mx.core.UIComponent;

	public class ElementIcon extends UIComponent
	{
		public static const SUBJECT:int = 1;
		public static const VERB:int = 2;
		public static const OBJECT:int = 3;
		
		private var _model:XML;

		private var _type:int; // SUBJECT/VERB/OBJECT
		private var dragging:Boolean = false;
		
		// 内部UIコンポーネント		
		private var textField:TextField = new TextField();
		// このアイコンに接続している関係線
		private var lines:Array = new Array();
		
		public function ElementIcon()
		{
			super();

			textField.selectable = false;
			textField.text = "初期値";
			this.addChild(textField);

			// イベントリスナの登録
	        addEventListener(Event.RENDER, onRender);

			// イベントリスナの登録（マウス）	        
        	addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        	addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
        	addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        	// ↓アイコンをドラック中，位置がずれることがあるのでいれてみたけど，関係なさそう
        	// addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);  
		}
		
		/**
		 * 描画イベント
		 */
		private function onRender(event:Event):void {
			// コンポーネントのサイズを設定します（この場所でやっていいのかどうかは不明）
			this.width = this.textField.textWidth;
			this.height = this.textField.textHeight;
			// 再描画します
			draw();
		}
		
		/**
		 * マウスボタンが押されたら，ドラッグを開始します．
		 * フラグを立て，ドラッグ中は関係線も再描画させます．
		 */
		private function onMouseDown(event:MouseEvent):void {
			this.startDrag();
			this.dragging = true;
		}
		
		/**
		 * ドラッグによる移動にあわせ，関係線を再描画させる
		 */
		private function onMouseMove(event:MouseEvent):void {
			if(this.dragging) {
				for(var i:int=0; i<lines.length; i++) {
					var li:LineIcon = lines[i] as LineIcon;
					li.redraw();
				}
			}
		}

		/**
		 * マウスボタンが離されたら，ドラッグを終了してモデルの座標を更新します
		 */		
		private function onMouseUp(event:MouseEvent):void {
			this.stopDrag();
			this.dragging = false;

			// モデルの座標を更新します
			this._model.attribute("x")[0] = this.x.toString();
			this._model.attribute("y")[0] = this.y.toString();
			trace(this + ":_model=" + this._model.toXMLString());
		}
		
		protected function draw():void {
			switch(this._type) {
				case ElementIcon.SUBJECT:
					this.graphics.lineStyle(0,0xFF3333);
					this.graphics.beginFill(0xF0F0F0);
					this.graphics.drawRoundRect(0,0,this.width,this.height,5,5);
					this.graphics.endFill();
					break;
				case ElementIcon.VERB:
					this.graphics.lineStyle(0,0x0000FF);
					this.graphics.beginFill(0xF0F0F0);
					this.graphics.drawRect(0,0,this.width,this.height);
					this.graphics.endFill();
					break;
				case ElementIcon.OBJECT:
					this.graphics.lineStyle(0,0xFFFF33);
					this.graphics.beginFill(0xF0F0F0);
					this.graphics.drawRect(0,0,this.width,this.height);
					this.graphics.endFill();
					break;
				default:
			}
		}
		
		public function addLine(line:LineIcon):void {
			this.lines.push(line);
		}
		
		public function get centerX():int {
			return this.x + (this.width / 2);
		}
		
		public function get centerY():int {
			return this.y + (this.height / 2);
		}
		
		/**
		 * モデルを設定する
		 */
		public function set model(_model:XML):void {
			this._model = _model; // これ，いるのかな？
			
			// ↓サイズを決定するため，ここで
			this.textField.text = this._model.text()[0]; // バインディング？？

			var name:String = _model.name();
			name = name.toUpperCase();
			if(name == "SUBJECT") {
				this._type = ElementIcon.SUBJECT;
			} else if(name == "VERB") {
				this._type = ElementIcon.VERB;
			} else if(name == "OBJECT") {
				this._type = ElementIcon.OBJECT;
			} else {
				trace(this + ":ERROR!!!");
			}
			
			if(this._model.attribute("x").length() == 0) {
				this.x = this.calculateNextX();
			} else {
				this.x = new Number(this._model.attribute("x")[0]);
			}
			
			if(this._model.attribute("y").length() == 0) {
				this.y = this.calculateNewY();
			} else {
				this.y = new Number(this._model.attribute("y")[0]);
			}
		}
		
		private static var nextElementY:int = 20;
		private static const INITIAL_SUBJCT_X:int = 20;
		private static const INITIAL_VERB_X:int = 120;
		private static const INITIAL_OBJECT_X:int = 220;
		
		private function calculateNextX():int {
			switch(this._type) {
				case ElementIcon.SUBJECT:
					return ElementIcon.INITIAL_SUBJCT_X;
				case ElementIcon.VERB:
					return ElementIcon.INITIAL_VERB_X;
				case ElementIcon.OBJECT:
					return ElementIcon.INITIAL_OBJECT_X;
				default:
					trace(this + ":ERROR");
					return 0;
			}
		}
		
		private function calculateNewY():int {
			var currentElementY:int = ElementIcon.nextElementY;
			if(this._type == ElementIcon.OBJECT) {
				ElementIcon.nextElementY += 20;
			}
			return currentElementY;
		}
		
		// ----------------------
		
		private var _entity:XML;
		
		public function set entity(value:XML):void {
			this._entity = value;	
			trace("set entity(value=" + value.toXMLString() + ")");
			
			// 表示を更新します
		}
		
		public function get entity():XML {
			return this._entity;
		}

		override public function toString():String {
			return this.entity.toXMLString();
		}
	}
}

/*
- Drag中のXY座標の変化を監視するためのイベント

        	addEventListener("xChanged", onXChanged);
        	addEventListener("yChanged", onYChanged);
		
		private function onXChanged(event:Event):void {
			trace(this + ".onXChanged(event=" + event);
		}
		
		private function onYChanged(event:Event):void {
			trace(this + ".onYChanged(event=" + event);
		}


*/